<template>
  <div class="drag-sign-contract">
    <van-nav-bar title="标题" :border="false" placeholder fixed>
      <template #left>
        <svg-icon name="arrows" @click="topReturnClick" />
      </template>
      <template #title>
        <span class="contract-title">待签文件</span>
      </template>
    </van-nav-bar>
    <div class="fixed-name">
      <div class="contract-name">{{ contractName }}</div>
    </div>
    <!-- 合同图片 -->
    <div class="contract-img">
      <van-list
        v-model:loading="loading"
        :finished="finished"
        @load="changeContractImageList"
        :immediate-check="false"
      >
        <template v-for="(item, index) in contractImageList" :key="item">
          <div class="contract-content">
            <img :src="`data:image/png;base64,${item}`" alt="" />
            <!-- 印章 -->
            <template v-for="signItem in sealImageList" :key="item">
              <div
                class="sign-write"
                :style="`width:${signItem.signWidth}px;height:${signItem.signHeight}px;top:${signItem.ycoord}px;left:${signItem.xcoord}px;`"
                :ref="(el) => (signRainRef[signItem.id] = el)"
                v-if="signItem.pageNum - 1 === index"
                @click="showBtnClick(signItem)"
                @touchstart="domOnTouchStart($event, signItem.id)"
                @touchmove="domOnTouchMove($event, signItem.id)"
                @touchend="domOnTouchEnd(signItem.id)"
              >
                <img :src="Base64Image" alt="" />
                <div class="sign-btn" v-show="signItem.showBtn">
                  <span @click="deleteSignImg(signItem.id)">删除</span>
                  <span @click="changeSignImg">换章</span>
                  <!-- <span>修改</span> -->
                  <span class="triangle"></span>
                </div>
              </div>
            </template>
          </div>
        </template>
      </van-list>
    </div>
    <div class="sign-bottom">
      <div class="sign" @click="writeSignClick('newAddSign')">
        <svg-icon name="write" className="write-icon" />
        <span class="write-text">手写签名</span>
      </div>
      <div class="sign">
        <svg-icon name="seal" className="write-icon" />
        <span class="write-text">盖章</span>
      </div>
      <van-button class="bottom-btn" type="primary" @click="signTypeSelect"
        >提交</van-button
      >
    </div>
  </div>
  <write-sign-img ref="writeSignImgRef" @signBase64Img="signBase64Img" />
  <!-- 刷脸签署 -->
  <face-swiping ref="faceSwipingRef" />
  <!-- 短信签署 -->
  <code-sign ref="codeSignRef" @codeSignClick="CodesignClick" />
</template>

<script lang="ts">
import { defineComponent, ref, reactive } from 'vue'
import { useStore } from '@/store'
import { useRoute, useRouter } from 'vue-router'
import { Dialog, Toast } from 'vant'
import WriteSignImg from '@/components/write-sign-img'
import faceSwiping from '@/components/face-swiping'
import CodeSign from '@/components/code-sign'

import { getItem, setItem } from '@/utils/storage'
import { generateUUID } from '@/utils/global-method'
import {
  getContractAllInfo,
  getContractBase64Img,
  postDragSignData,
  getSigningPattern
} from '@/api/contract'

export default defineComponent({
  components: { WriteSignImg, faceSwiping, CodeSign },
  setup() {
    const route = useRoute()
    const router = useRouter()
    const store = useStore()
    const contractId = ref('')
    const contractName = ref('')
    const contractImageList = ref<any>([]) // 合同图片信息
    const loading = ref(false)
    const finished = ref(false)
    const imageData = reactive({
      total: 0,
      PageNumber: 1,
      filePath: ''
    })
    contractId.value = route.query.contractId as string
    // 获取合同信息
    const getContractList = async () => {
      const res = await getContractAllInfo({ contractId: contractId.value })
      if (res.code !== '0') return
      const list = res.data
      contractName.value = list.contractBaseInfo.title // 代签文件
      const fileList = list.signingFileInfoList.map((item: any) => {
        return {
          fileId: item.fileId,
          fileName: item.fileName,
          filePath: item.filePath,
          filePages: item.filePages
        }
      })
      imageData.total = fileList[0].filePages
      imageData.filePath = fileList[0].filePath
      changeContractImageList()
    }
    // 请求图片信息
    const changeContractImageList = async () => {
      for (let i = imageData.PageNumber; i <= imageData.PageNumber; i++) {
        const res = await getContractBase64Img({
          filePath: imageData.filePath,
          pageNum: i
        })
        if (res.code !== '0') return
        contractImageList.value.push(res.data)
      }
      imageData.PageNumber++
      loading.value = false
      if (contractImageList.value.length >= imageData.total) {
        finished.value = true
      }
    }
    // 返回按钮
    const topReturnClick = () => {
      router.push({
        path: '/check-contract',
        query: {
          contractId: contractId.value
        }
      })
    }
    // 手写签名
    const writeSignImgRef = ref<InstanceType<typeof WriteSignImg>>()
    const writeSignClick = (signType: string) => {
      writeSignImgRef.value!.showWriteSignClick(signType)
    }
    // 选择签名
    const Base64Image = ref('') // 签名
    Base64Image.value =
      getItem(`${contractId.value}_${route.query.uuid}_signImg`) ?? ''
    // 印章信息接口
    interface ISealImageItem {
      id: string
      pageNum: number
      xcoord: number
      ycoord: number
      xpercent: number
      ypercent: number
      signWidth: number
      signHeight: number
      showBtn: boolean
    }
    const sealImageList = ref<ISealImageItem[]>([]) // 签名列表
    sealImageList.value =
      getItem(`${contractId.value}_${route.query.uuid}_cooreds`) ?? []
    const contractH = route.query.contractH as any
    const contractW = route.query.contractW as any
    // 合同当前页数
    const currentNumberPages = (elClass: string) => {
      const el: HTMLDivElement = document.querySelector(`.${elClass}`)!
      const height = el.offsetHeight + 10
      const top = el.scrollTop
      const pageNum = Math.round(top / height) + 1
      return pageNum
    }
    const signBase64Img = (base64: string, signType: string) => {
      if (signType === 'newAddSign') {
        const currentPages = currentNumberPages('contract-img')
        Base64Image.value = base64
        const signData: ISealImageItem = {
          id: generateUUID(),
          pageNum: currentPages,
          xcoord: (50 * contractW) / 100,
          ycoord: (50 * contractH) / 100,
          xpercent: 50,
          ypercent: 50,
          signWidth: Math.round(contractW * 0.095), // 36
          signHeight: Math.round(contractH * 0.048), // 25
          showBtn: true
        }
        if (Base64Image.value && base64 !== Base64Image.value) {
          Dialog.confirm({
            title: '所选印章与当前印章不同',
            message: '是否使用当前所选印章'
          })
            .then(() => {
              sealImageList.value.push(signData)
            })
            .catch(() => {})
        } else {
          sealImageList.value.push(signData)
        }
      } else if (signType === 'changeSign') {
        Base64Image.value = base64
      }
    }
    // 拖拽事件
    const signRainRef = ref<any>({})
    const signObj = reactive({
      // 鼠标位置
      x: 0,
      y: 0,
      // 鼠标移动距离
      nx: 0,
      ny: 0,
      // 盒子位置
      dx: 0,
      dy: 0,
      // 盒子移动后的距离
      xPum: 0,
      yPum: 0,
      flags: false
    })
    const approve = (e: any) => {
      e.preventDefault()
    }
    const domOnTouchStart = (e: any, id: string) => {
      const el = signRainRef.value![id]
      const touch = e.touches[0] ?? e
      signObj.flags = true
      signObj.x = touch.clientX
      signObj.y = touch.clientY
      signObj.dx = el.offsetLeft
      signObj.dy = el.offsetTop
      signObj.xPum = signObj.dx
      signObj.yPum = signObj.dy
    }
    const domOnTouchMove = (e: any, id: string) => {
      const el = signRainRef.value![id]
      if (!signObj.flags) return
      const touch = e.touches[0] ?? e
      signObj.nx = touch.clientX - signObj.x
      signObj.ny = touch.clientY - signObj.y
      signObj.xPum = signObj.dx + signObj.nx
      signObj.yPum = signObj.dy + signObj.ny
      const maxWidth = contractW - el.offsetWidth
      const maxHeight = contractH - el.offsetHeight
      if (signObj.xPum < 0) {
        signObj.xPum = 0
      } else if (signObj.xPum > maxWidth) {
        signObj.xPum = maxWidth
      }
      if (signObj.yPum < 0) {
        signObj.yPum = 0
      } else if (signObj.yPum > maxHeight) {
        signObj.yPum = maxHeight
      }
      el.style.left = signObj.xPum + 'px'
      el.style.top = signObj.yPum + 'px'
      window.addEventListener('touchmove', approve, {
        passive: false
      })
    }
    const domOnTouchEnd = (id: string) => {
      signObj.flags = false
      window.removeEventListener('touchmove', approve)
      const signData = sealImageList.value.find(
        (item: ISealImageItem) => item.id === id
      )!
      signData.xpercent = +(100 - (signObj.yPum / contractH) * 100).toFixed(2)
      signData.ypercent = +((signObj.xPum / contractW) * 100).toFixed(2)
      signData.xcoord = signObj.xPum
      signData.ycoord = signObj.yPum
    }

    // 印章删除
    const deleteSignImg = (id: string) => {
      Dialog.confirm({
        title: '确定要删除当前印章吗?'
      })
        .then(() => {
          const index = sealImageList.value.findIndex(
            (item: ISealImageItem) => item.id === id
          )
          if (~index) {
            sealImageList.value.splice(index, 1)
            Toast.success('删除成功')
          }
        })
        .catch(() => {})
    }
    // 换章
    const changeSignImg = () => {
      Dialog.confirm({
        title: '确定要更换所有印章吗?'
      })
        .then(() => {
          writeSignClick('changeSign')
        })
        .catch(() => {})
    }

    // 印章操作按钮显示隐藏点击事件
    const showBtnClick = (signItem: any) => {
      const data = sealImageList.value.find(
        (item: ISealImageItem) => item.id === signItem.id
      )!
      data.showBtn = !data.showBtn
    }

    // 立即签署
    const authcWay = ref(2) // 2为短信，3为刷脸
    const changeSignPattern = async () => {
      const res = await getSigningPattern()
      if (res.code !== '0') return
      authcWay.value =
        +res.data.org.orgBasicInfoConfigEntity.userSignModeConfigValue
    }
    const faceSwipingRef = ref<InstanceType<typeof faceSwiping>>()
    const codeSignRef = ref<InstanceType<typeof CodeSign>>()
    const signTypeSelect = () => {
      console.log(codeSignRef.value)
      if (!Base64Image.value || !sealImageList.value.length) {
        return Toast.fail('至少加盖一个签名')
      }
      if (authcWay.value === 2) {
        codeSignRef.value!.showCodeSignPopup()
      } else if (authcWay.value === 3) {
        // 存储当前控件
        const coordsKey = `${contractId.value}_${route.query.uuid}_cooreds`
        const signImg = `${contractId.value}_${route.query.uuid}_signImg`
        setItem(coordsKey, sealImageList.value)
        setItem(signImg, Base64Image.value)
        faceSwipingRef.value!.showFaceSwipingPopup()
      }
    }
    // 短信签
    const CodesignClick = async (data: {
      vcode: string
      randomCode: number
    }) => {
      const coords = sealImageList.value.map((item: ISealImageItem) => {
        return {
          pageNum: item.pageNum,
          xcoord: item.xcoord,
          ycoord: item.ycoord,
          xpercent: item.xpercent,
          ypercent: item.ypercent
        }
      })
      const uuid = new Date().getTime()
      const params = {
        contractId: contractId.value,
        bizNo: uuid,
        sealImg: Base64Image.value.replace(/^data:image\/\w+;base64,/, ''),
        authcWay: authcWay.value,
        coords: coords, // 章
        vcode: data.vcode,
        randomCode: data.randomCode
      }
      const res = await postDragSignData(params)
      if (res.code !== '0') return
      router.push({
        path: '/contract-sign-success',
        query: {
          contractId: contractId.value
        }
      })
    }
    // 刷脸签
    const faceSwipingSignClick = async () => {
      const coords = sealImageList.value.map((item: ISealImageItem) => {
        return {
          pageNum: item.pageNum,
          xcoord: item.xcoord,
          ycoord: item.ycoord,
          xpercent: item.xpercent,
          ypercent: item.ypercent
        }
      })
      const uuid = new Date().getTime()
      const orderNo = getItem('bizNo')
      const params = {
        contractId: contractId.value,
        bizNo: uuid,
        sealImg: Base64Image.value.replace(/^data:image\/\w+;base64,/, ''),
        authcWay: authcWay.value,
        coords: coords, // 章
        faceDto: {
          realName: store.state.login.userInfo.userName,
          certificateNumber: store.state.login.userInfo.idNumber,
          isPhone: true,
          orderNo: orderNo // 订单号
        }
      }
      const res = await postDragSignData(params)
      if (res.code !== '0') return
      router.push({
        path: '/contract-sign-success',
        query: {
          contractId: contractId.value
        }
      })
    }
    // 初始化数据
    const init = async () => {
      await getContractList()
      await changeSignPattern()
      // 刷脸回调
      if (route.query.thirdparty) {
        await faceSwipingSignClick()
      }
    }
    init()

    return {
      codeSignRef,
      signRainRef,
      faceSwipingRef,
      Base64Image,
      contractName,
      loading,
      finished,
      contractImageList,
      writeSignImgRef,
      sealImageList,
      topReturnClick,
      changeContractImageList,
      writeSignClick,
      signBase64Img,
      showBtnClick,
      domOnTouchStart,
      domOnTouchMove,
      domOnTouchEnd,
      deleteSignImg,
      changeSignImg,
      CodesignClick,
      signTypeSelect
    }
  }
})
</script>

<style scoped lang="less">
.drag-sign-contract {
  position: relative;
  width: 100%;
  height: 100%;
  .contract-title {
    font-size: 17px;
    color: #101010;
    font-weight: 700;
  }
  .fixed-name {
    height: 41px;
    width: 100%;
    .contract-name {
      position: fixed;
      top: 46px;
      left: 0;
      height: 40px;
      width: 100%;
      background-color: #fff;
      border-bottom: 1px solid #e0e0e0;
      font-size: 13px;
      line-height: 41px;
      padding-left: 20px;
      color: #101010;
    }
  }
  .contract-img {
    height: calc(100% - 147px);
    overflow: hidden;
    overflow-y: auto;
    .contract-content {
      position: relative;
      margin-bottom: 10px;
      img {
        display: block;
        width: 100%;
      }
      // 印章
      .sign-write {
        position: absolute;
        border: 1px dashed rgb(0, 175, 161);
        background: rgb(220, 230, 241);
        img {
          display: block;
          width: 100%;
          height: 100%;
        }
        .sign-btn {
          position: absolute;
          top: -45px;
          left: -50% + -90px;
          margin: auto;
          display: flex;
          justify-content: space-around;
          align-items: center;
          width: 141px;
          height: 32px;
          border-radius: 5px;
          background: rgb(127, 127, 127);
          font-size: 14px;
          color: #fff;
          .triangle {
            position: absolute;
            bottom: -20px;
            display: block;
            width: 0px;
            height: 0px;
            border-width: 10px;
            border-style: solid;
            border-color: #7f7f7f transparent transparent transparent;
          }
        }
      }
    }
  }
  .sign-bottom {
    position: fixed;
    bottom: 0;
    left: 0;
    height: 59px;
    width: 100%;
    background-color: #fff;
    border-top: 1px solid #e0e0e0;
    display: flex;
    justify-content: space-around;
    align-items: center;
    .sign {
      display: flex;
      align-items: center;
      .write-icon {
        font-size: 19px;
        margin-right: 7px;
      }
      .write-text {
        font-size: 12px;
      }
    }
    .bottom-btn {
      width: 140px;
      height: 40px;
      font-size: 16px;
    }
  }
}
</style>
